package com.alibaba.algo.apiimpl.user;

import com.alibaba.algo.annotation.OperateLogAnnotation;
import com.alibaba.algo.constants.Constants;
import com.alibaba.algo.cooperation.common.BaseResult;
import com.alibaba.algo.cooperation.usercomponent.service.user.SysPositionService;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.CreatePositionReqVo;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.CreatePositionRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.DeletePositionRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.SavePositionRequestForSyncVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.SelectOrgPositionReqVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.SelectPositionListRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.UpdatePositionRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.res.user.SelectPositionInfoResVO;
import com.alibaba.algo.cooperation.usercomponent.vo.res.user.SelectPositionListResponseVO;
import com.alibaba.algo.core.base.PagerEntity;
import com.alibaba.algo.core.base.YesOrNo;
import com.alibaba.algo.core.exception.BaseException;
import com.alibaba.algo.dao.user.SysPositionMapper;
import com.alibaba.algo.domain.user.SysEmployeePositionDomain;
import com.alibaba.algo.domain.user.SysOrgDomain;
import com.alibaba.algo.domain.user.SysPositionDomain;
import com.alibaba.algo.dtos.user.SysPositionDTO;
import com.alibaba.algo.entity.user.SysEmployeePosition;
import com.alibaba.algo.entity.user.SysOrg;
import com.alibaba.algo.entity.user.SysPosition;
import com.alibaba.algo.enums.OperateTypeEnum;
import com.alibaba.algo.enums.ResourceTypeEnum;
import com.alibaba.algo.enums.SysMainPositionEnum;
import com.alibaba.algo.exception.BaseErrorCode;
import com.alibaba.algo.exception.SysPositionErrorCode;
import com.alibaba.algo.util.StringUtil;
import com.alibaba.algo.utils.ConverterUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 类SysPositionServiceImpl.java的实现描述：岗位 serviceimpl
 *
 * @author nieganggang 2021-03-12 16:08:17
 */
@Slf4j
@RestController
public class SysPositionServiceImpl implements SysPositionService {

    @Autowired
    private SysPositionDomain sysPositionDomain;

    @Autowired
    private SysOrgDomain sysOrgDomain;

    @Resource
    private SysPositionMapper sysPositionMapper;

    @Autowired
    private SysEmployeePositionDomain sysEmployeePositionDomain;

    @Autowired
    private SysUserCacheServiceImpl sysUserCacheService;

    /**
     * 支持批量新增岗位列表
     * 新增原则:
     * 1、一个组织只有一个主岗,如果已有主岗,新增时替换原来的主岗
     *
     * @param vo 入参
     * @return 新增结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult save(List<CreatePositionRequestVO> vo) {
        log.debug("SysPositionServiceImpl save param... vo:{}", JSON.toJSONString(vo));
        if (CollectionUtils.isEmpty(vo)) {
            return BaseResult.buildSuccess();
        }
        // 获取入参中主岗数量数量,如果大于1,抛异常
        Long mainPositionNum = vo.stream().filter(createPositionRequestVO -> SysMainPositionEnum.MAIN.getValue().equals(createPositionRequestVO.getIsPrimary().intValue())).count();
        if (mainPositionNum > 1) {
            throw new BaseException(SysPositionErrorCode.HAS_UNIQUE_MAIN_POSITION.getCode(), SysPositionErrorCode.HAS_UNIQUE_MAIN_POSITION.getMessage());
        }
        // 先判断是否已有主岗,如果有再更新数据库中的主岗,否则,不更新
        if (mainPositionNum > 0) {
            sysPositionDomain.updateMainPositionByOrgId(vo.get(0).getOrgId());
        }

        // 入库
        for (CreatePositionRequestVO createPositionRequestVO : vo) {
            SysPosition sysPosition = new SysPosition();
            sysPosition.setOrgId(createPositionRequestVO.getOrgId());
            sysPosition.setName(createPositionRequestVO.getName());
            SysPosition old = sysPositionDomain.getOne(sysPosition);
            if (!ObjectUtils.isEmpty(old)) {
                continue;
            }
            BeanUtils.copyProperties(createPositionRequestVO, sysPosition);
            sysPositionDomain.insert(sysPosition);
        }
        return BaseResult.buildSuccess();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = true, rollbackFor = Exception.class)
    public BaseResult getPositionNumByOrgId(SelectOrgPositionReqVO vo) {
        Long orgId = vo.getOrgId();
        if (ObjectUtils.isEmpty(orgId)) {
            throw new BaseException(BaseErrorCode.ORG_ID_IS_NULL.getCode(), BaseErrorCode.ORG_ID_IS_NULL.getMessage());
        }
        SysPosition sysPosition = new SysPosition();
        sysPosition.setOrgId(orgId);
        Integer counts = sysPositionDomain.countByPara(sysPosition);
        return BaseResult.buildSuccess(counts);
    }

    /**
     * 查询组织下的岗位信息
     *
     * @param vo 组织列表
     * @return 岗位列表
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = true, rollbackFor = Exception.class)
    public BaseResult qryPositionListByOrgId(SelectOrgPositionReqVO vo) {
        Long orgId = vo.getOrgId();
        if (ObjectUtils.isEmpty(orgId)) {
            throw new BaseException(BaseErrorCode.ORG_ID_IS_NULL.getCode(), BaseErrorCode.ORG_ID_IS_NULL.getMessage());
        }
        SysPosition sysPosition = new SysPosition();
        sysPosition.setOrgId(orgId);
        List<SysPosition> sysPositionList = sysPositionDomain.listByPara(sysPosition, null);
        List<SelectPositionInfoResVO> resVOList = new ArrayList<>();
        sysPositionList.forEach(s -> {
            SelectPositionInfoResVO resVO = new SelectPositionInfoResVO();
            resVO.setId(s.getId());
            resVO.setName(s.getName());
            resVOList.add(resVO);
        });
        return BaseResult.buildSuccess(resVOList);
    }

    /**
     * 更新为主岗
     *
     * @param vo 岗位标识
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult updateMain(UpdatePositionRequestVO vo) {
        long orgId = sysPositionDomain.selectOrgByPositionId(vo.getId());
        sysPositionDomain.updateMainPositionByOrgId(orgId);

        SysPosition sysPosition = new SysPosition();
        BeanUtils.copyProperties(vo, sysPosition);
        sysPosition.setIsPrimary(SysMainPositionEnum.MAIN.getValue().longValue());
        sysPositionDomain.updateById(sysPosition);
        return BaseResult.buildSuccess();
    }

    /**
     * 更新为非主岗
     *
     * @param vo 岗位标识
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult updateNonMain(UpdatePositionRequestVO vo) {
        SysPosition sysPosition = new SysPosition();
        BeanUtils.copyProperties(vo, sysPosition);
        sysPosition.setIsPrimary(SysMainPositionEnum.NON_MAIN.getValue().longValue());
        sysPositionDomain.updateById(sysPosition);
        return BaseResult.buildSuccess();
    }

    /**
     * 岗位删除
     *
     * @param positionIdList 岗位主键
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult delete(List<Long> positionIdList) {
        if (CollectionUtils.isEmpty(positionIdList)) {
            log.info("SysPositionServiceImpl delete positionIdList is null");
            return BaseResult.buildError("参数不能为空");
        }
        List<String> positionNameList = new ArrayList<>();
        for (Long id : positionIdList) {
            if (null == id || id<=0) {
                continue;
            }
            SysEmployeePosition sysEmployeePosition = new SysEmployeePosition();
            sysEmployeePosition.setPositionId(id);
            sysEmployeePosition.setIsDeleted("N");
            int iCnt = sysEmployeePositionDomain.countByPara(sysEmployeePosition);
            if (iCnt > 0) {
                SysPosition sysPosition = sysPositionDomain.getById(id);
                positionNameList.add(sysPosition.getName());
            }
        }
        if (!CollectionUtils.isEmpty(positionNameList)) {
            String positionNames = String.join(",", positionNameList);
            String tipMsg = String.format("岗位下还有员工，请先移除!岗位：%s", positionNames);
            log.info(tipMsg);
            return BaseResult.buildError(tipMsg);
        }

        for (Long id : positionIdList) {
            if (null == id || id<=0) {
                continue;
            }
            SysPosition position = new SysPosition();
            position.setId(id);
            position.setIsDeleted(YesOrNo.Y.name());
            position.setGmtModified(LocalDateTime.now());
            sysPositionDomain.updateById(position);
        }

        // 说明：此处无需清理缓存，因为前面有限制条件，必须先解除与员工的关系，而缓存全是基于用户员工维度存在的
        return BaseResult.buildSuccess();
    }

    /**
     * 组织下岗位管理分页查询
     *
     * @param vo 组织id
     * @return 岗位分页列表
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = true, rollbackFor = Exception.class)
    public BaseResult<com.alibaba.algo.core.base.PagerEntity<SelectPositionListResponseVO>> selectPage(SelectPositionListRequestVO vo) {
        if (ObjectUtils.isEmpty(vo.getPageIndex())) {
            throw new BaseException(BaseErrorCode.PAGE_INDEX_IS_NULL.getCode(), BaseErrorCode.PAGE_INDEX_IS_NULL.getMessage());
        }
        if (ObjectUtils.isEmpty(vo.getPageSize())) {
            throw new BaseException(BaseErrorCode.PAGE_SIZE_IS_NULL.getCode(), BaseErrorCode.PAGE_SIZE_IS_NULL.getMessage());
        }
//        if (ObjectUtils.isEmpty(vo.getOrgId())) {
//            throw new BaseException(BaseErrorCode.ORG_ID_IS_NULL.getCode(), BaseErrorCode.ORG_ID_IS_NULL.getMessage());
//        }
        // 主岗位列在前面
        LinkedHashMap<String, Object> sortMap = new LinkedHashMap<String, Object>();
        sortMap = ObjectUtils.isEmpty(vo.getSortMap()) ? sortMap : vo.getSortMap();
        sortMap.put("isPrimary", "DESC");
        sortMap.put("gmtCreated", "DESC");
        SysPosition positionCon = new SysPosition();
        BeanUtils.copyProperties(vo, positionCon);
        PagerEntity pagerEntity = sysPositionDomain.pageByPara(positionCon, vo.getPageIndex(), vo.getPageSize(), sortMap);
        List<SelectPositionListResponseVO> resultList = new ArrayList<>();
        List<SysPosition> sysPositionList = (List<SysPosition>) pagerEntity.getDataList();
        for (SysPosition position : sysPositionList) {
            SelectPositionListResponseVO resVO = new SelectPositionListResponseVO();
            BeanUtils.copyProperties(position, resVO);
            Long orgId = position.getOrgId();
            SysOrg sysOrg = sysOrgDomain.getById(orgId);
            if (!ObjectUtils.isEmpty(sysOrg)) {
                resVO.setOrgName(sysOrg.getOrgName());
            }
            resultList.add(resVO);
        }
        com.alibaba.algo.core.base.PagerEntity<SelectPositionListResponseVO> resPage = new com.alibaba.algo.core.base.PagerEntity(pagerEntity.getTotal(), pagerEntity.getTotalPages(), pagerEntity.getPageSize(), pagerEntity.getPageIndex(), resultList);
        return BaseResult.buildSuccess(resPage);
    }

    /**
     * 查询全量岗位信息,不区分组织
     *
     * @return 岗位列表
     */
    @Override
    public BaseResult qryAllPositions() {
        LinkedHashMap<String, Object> sortMap = new LinkedHashMap<String, Object>();
        sortMap.put("gmtCreated", "DESC");
        List<SysPosition> sysPositionList = sysPositionDomain.listByPara(new SysPosition(), sortMap);
        List<SelectPositionListResponseVO> result = new ArrayList<>();
        for (SysPosition sysPosition : sysPositionList) {

            SelectPositionListResponseVO selectPositionListResponseVO = new SelectPositionListResponseVO();
            //剔除已被逻辑删除,或者物理删除的组织下属岗位
            SysOrg tmpOrg = sysOrgDomain.selectByOrgId(sysPosition.getOrgId());
            if (tmpOrg == null) {
                continue;
            }
            String orgName = tmpOrg.getOrgName();

            selectPositionListResponseVO.setName(sysPosition.getName());
            selectPositionListResponseVO.setId(sysPosition.getId());
            selectPositionListResponseVO.setIsPrimary(sysPosition.getIsPrimary());
            selectPositionListResponseVO.setOrgName(orgName);

            result.add(selectPositionListResponseVO);
        }
        return BaseResult.buildSuccess(result);
    }


    public BaseResult<SelectPositionListResponseVO> getById(Long id) {
        SysPosition position = sysPositionDomain.getById(id);
        SelectPositionListResponseVO resVo = ConverterUtil.getInstance().map(position, SelectPositionListResponseVO.class);
        return BaseResult.buildSuccess(resVo);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @OperateLogAnnotation(resouceType = ResourceTypeEnum.POSITION, operateType = OperateTypeEnum.DELETE)
    public BaseResult deletePositionByPosCode(DeletePositionRequestVO deletePositionRequestVO) {
        log.info("SysPositionServiceImpl deletePositionByPosCode,param:{}", JSON.toJSONString(deletePositionRequestVO));
        //根据posCode查出岗位id后，根据岗位id删除员工与岗位关联数据 物理删除
        SysPosition param = new SysPosition();
        param.setPosCode(deletePositionRequestVO.getPosCode());
        SysPosition sysPositionFromDB = sysPositionDomain.getPositionDetail(param);
        if (!ObjectUtils.isEmpty(sysPositionFromDB) && null != sysPositionFromDB.getId() && sysPositionFromDB.getId() > 0) {
            //sysEmployeePositionDomain.deleteByPositionId(sysPositionFromDB.getId());
            SysEmployeePosition sysEmployeePosition = new SysEmployeePosition();
            sysEmployeePosition.setPositionId(sysPositionFromDB.getId());
            sysEmployeePosition.setIsDeleted(YesOrNo.Y.name());
            sysEmployeePosition.setModifier(Constants.ORIGIN_SAP);
            sysEmployeePosition.setGmtModified(LocalDateTime.now());
            int iUpEmpRtn=sysEmployeePositionDomain.updateByPositionId(sysEmployeePosition);
            log.info("SysPositionService.deletePositionByPosCode iRtn:{},positionId:{}", iUpEmpRtn, sysEmployeePosition.getId());
        }
        //根据posCode删除岗位信息
        //sysPositionDomain.deleteByPosCode(deletePositionRequestVO.getPosCode());
        SysPosition sysPosition = new SysPosition();
        sysPosition.setPosCode(deletePositionRequestVO.getPosCode());
        sysPosition.setIsDeleted(YesOrNo.Y.name());
        sysPosition.setModifier(Constants.ORIGIN_SAP);
        sysPosition.setGmtModified(LocalDateTime.now());
        int iUpPosRtn = 0;
        if(!StringUtils.isEmpty(sysPosition.getPosCode())){
            iUpPosRtn = sysPositionDomain.updateByPosCode(sysPosition);
            log.info("SysPositionService.deletePositionByPosCode iRtn:{},positionCode:{}", iUpPosRtn, sysPosition.getPosCode());
        }
        //删除缓存
        if (iUpPosRtn > 0 && null != sysPositionFromDB && null != sysPositionFromDB.getId() && sysPositionFromDB.getId()>0) {
            sysUserCacheService.deleteUserFromCacheByPositionUpdate(sysPositionFromDB.getId());
        }
        return BaseResult.buildSuccess();
    }

    @Override
    @OperateLogAnnotation(resouceType = ResourceTypeEnum.POSITION, operateType = OperateTypeEnum.INSERT_OR_UPDATE)
    public BaseResult saveOrUpdatePositionForSync(SavePositionRequestForSyncVO savePositionRequestForSyncVO) {
        log.info("SysPositionServiceImpl saveOrUpdatePositionForSync,param:{}", JSON.toJSONString(savePositionRequestForSyncVO));
        SysPosition sysPosition = new SysPosition();
        BeanUtils.copyProperties(savePositionRequestForSyncVO, sysPosition);
        sysPosition.setName(savePositionRequestForSyncVO.getPosName());
        //根据orgCode查询orgId
        SysOrg sysOrg = sysOrgDomain.qryOrgByOrgCode(savePositionRequestForSyncVO.getOrgCode());
        if (!ObjectUtils.isEmpty(sysOrg)) {
            sysPosition.setOrgId(sysOrg.getId());
        }
        sysPosition.setIsDeleted(YesOrNo.N.name());
        sysPosition.setIsPrimary(1L);//默认为主岗
        log.info("SysPositionServiceImpl saveOrUpdatePositionForSync,sysPosition:{}", JSON.toJSONString(sysPosition));
        Integer optResult = sysPositionDomain.saveOrUpdatePositionForSync(sysPosition);
        if (null != optResult && optResult > 0) {
            // 删除缓存
            SysPosition param = new SysPosition();
            param.setPosCode(savePositionRequestForSyncVO.getPosCode());
            SysPosition sysPositionFromDB = sysPositionDomain.getPositionDetail(param);
            if (null != sysPositionFromDB && null != sysPositionFromDB.getId() && sysPositionFromDB.getId() > 0) {
                sysUserCacheService.deleteUserFromCacheByPositionUpdate(sysPositionFromDB.getId());
            }
            return BaseResult.buildSuccess();
        } else {
            return BaseResult.buildError("岗位信息新增或更新失败");
        }
    }

    public List<String> listDistinctPositionNames() {
        return sysPositionMapper.listDistinctPositionNames();
    }


    /**
     * 更新岗位信息
     *
     * @param vo
     * @return
     */
    @Override
    public BaseResult updatePosition(@Valid UpdatePositionRequestVO vo) {
        // 检查参数合法性
        if (null == vo) {
            return BaseResult.buildError("参数不能为空");
        }
        if (null == vo.getId() || vo.getId() <= 0) {
            return BaseResult.buildError("岗位ID不能为空");
        }

        SysPosition originInfo = sysPositionDomain.getById(vo.getId());
        if (ObjectUtils.isEmpty(originInfo)) {
            return BaseResult.buildError("不存在的岗位!");
        }
        Long orgId = originInfo.getOrgId();
        //一个组织下面只允许一个主岗
        if (!ObjectUtils.isEmpty(vo.getIsPrimary()) && vo.getIsPrimary() > 0) {
            SysPosition param = new SysPosition();
            param.setOrgId(orgId);
            param.setIsPrimary(1L);
            SysPosition primaryPosition = sysPositionMapper.getOne(param, null);
            if (!ObjectUtils.isEmpty(primaryPosition) && !vo.getId().equals(primaryPosition.getId())) {
                return BaseResult.buildError("组织下已有主岗!");
            }
        }
        //相同组织下面的岗位名称唯一
        if (!StringUtil.isEmpty(vo.getName())) {
            SysPosition param = new SysPosition();
            param.setOrgId(orgId);
            param.setName(vo.getName());
            SysPosition namePosition = sysPositionMapper.getOne(param, null);
            if (!ObjectUtils.isEmpty(namePosition) && !vo.getId().equals(namePosition.getId())) {
                return BaseResult.buildError("组织已有该岗位名称!");
            }
        }
        SysPosition positionDO = ConverterUtil.getInstance().map(vo, SysPosition.class);
        positionDO.setGmtModified(LocalDateTime.now());
        int iRtn = sysPositionDomain.updateById(positionDO);
        if (iRtn > 0) {
            // 删除缓存，涉及情况：1、岗位编码或名称修改
            sysUserCacheService.deleteUserFromCacheByPositionUpdate(vo.getId());
        }
        return BaseResult.buildSuccess(true);
    }


    /**
     * 岗位新增
     *
     * @param vo
     * @return
     */
    @Override
    public BaseResult addPosition(@Valid CreatePositionReqVo vo) {
        List<Long> orgIdList = vo.getOrgIdList();
        List<String> primaryExistList = Lists.newArrayList();
        List<String> nameExistList = Lists.newArrayList();
        List<SysPosition> positions = orgIdList.stream().filter(orgId -> {
            //每个组织下面岗位唯一
            List<SysPositionDTO> originPositions = sysPositionDomain.listPositionOrg(orgId);
            boolean isNameExist = originPositions.stream().anyMatch(item -> vo.getName().equals(item.getName()));
            if (isNameExist) {
                nameExistList.add(originPositions.get(0).getOrgName());
            }
            boolean primaryExist = false;
            //只有一个主岗
            if (!ObjectUtils.isEmpty(vo.getIsPrimary()) && vo.getIsPrimary().equals(1L)) {
                primaryExist = originPositions.stream().anyMatch(item -> vo.getIsPrimary().equals(1L));
            }
            if (primaryExist) {
                primaryExistList.add(originPositions.get(0).getOrgName());
            }
            return !isNameExist && !primaryExist;
        }).map(orgId -> {
            SysPosition position = ConverterUtil.getInstance().map(vo, SysPosition.class);
            position.setOrgId(orgId);
            position.setGmtCreated(LocalDateTime.now());
            position.setGmtModified(LocalDateTime.now());
            //生成岗位编码 唯一
            StringBuilder sb = new StringBuilder();
            String postStr = StringUtil.getRandomStr(3, StringUtil.NUMBERS);
            String posCode = sb.append(orgId).append(postStr).toString();
            position.setPosCode(posCode);
            return position;
        }).collect(Collectors.toList());
        Long res = sysPositionDomain.saveBatch(positions);
        String nameMsg = "";
        String primaryMsg = "";
        if (!nameExistList.isEmpty()) {
            nameMsg = String.format("%s组织下已存在该岗位,添加失败.", nameExistList);
        }
        if (!primaryExistList.isEmpty()) {
            primaryMsg = String.format("%s组织下已存在主岗,添加失败.", primaryExistList);
        }
        String msg = String.format("%s%s添加岗位成功数量%d", nameMsg, primaryMsg, res);
        return BaseResult.buildSuccess(msg, res);
    }

    @Override
    public BaseResult qryPositionListByOrgIdAndName(SelectPositionListRequestVO vo) {
        List<SysPosition> sysPositionList = sysPositionDomain.qryPositionListByOrgIdAndName(vo);
        return BaseResult.buildSuccess(sysPositionList);
    }
};


